package edu.ustb.aur.moldpackage;

import java.util.HashMap;
import java.util.List;

import com.alibaba.fastjson.JSONObject;
import edu.ustb.aur.assetpackage.Asset;
import edu.ustb.aur.myenum.MoldEnum;
import edu.ustb.aur.myenum.RightEnum;
import edu.ustb.aur.rightpackage.AbstractRight;
import edu.ustb.aur.utils.PercentageOperate;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author mold是对权利初始化，对权利的使用进行限制——操作规则 抽象的资产、权利与用户的结合
 */
public abstract class AbstractMold {

    /**
     * 标识继承类的类型，用于反序列化
     */
    public String type;

    /**
     * 构造资产对象与权利对象的映射 RightEnum 权利枚举 AbstractRight 抽象权利类，包含rightMap<userAddress, percentage>
     */
    HashMap<RightEnum, AbstractRight> moldMap;
    /**
     * 阈值
     */
    @ApiParam(name = "mold", value = "阈值", required = true)
    double threshold;

    /**
     * 默认构造函数
     */
    public AbstractMold() {
        this.moldMap = new HashMap<>();
        this.threshold = 1.0;
    }

    /**
     * 带参构造函数 对于threshold的简单说明： threshold = 1.0 代表共有中的集体共有（或是私有） threshold = 2/3 代表共有中的按比例共有
     * 
     * @param moldMap
     *            构造资产对象与权利对象的映射
     * @param threshold
     *            阈值
     */
    public AbstractMold(HashMap<RightEnum, AbstractRight> moldMap, double threshold) {
        this.moldMap = moldMap;
        this.threshold = threshold;
    }

    /**
     * 阈值的设置 TODO 添加是否具有修改阈值的判断
     * 
     * @param threshold
     *            阈值
     */
    public void setThreshold(double threshold) {
        this.threshold = threshold;
    }

    /**
     * 获取阈值
     * 
     * @return 阈值
     */
    public Double getThreshold() {
        return this.threshold;
    }

    public HashMap<RightEnum, AbstractRight> getMoldMap() {
        return moldMap;
    }

    public void setMoldMap(HashMap<RightEnum, AbstractRight> moldMap) {
        this.moldMap = moldMap;
    }

    /**
     * 获取mold类型
     * 
     * @return mold类型
     */
    public String getType() {
        return this.type;
    }

    /**
     * 售卖操作，判断各权利是否均操作阈值，符合条件就执行。同意者的rightMap各权利之和超过阈值，强制执行此操作，原权利映射注销，新的权利映射建立 规定了售卖操作需要具有的权利，规定了售卖操作需要完成的权利转移
     * 目前假定进行售卖操作，需要具有收益权，占有权，处分权，并且其具有的比例操作阈值
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    public abstract boolean sell(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap);

    /**
     * 租赁返回操作，判断各权利是否均操作阈值，符合条件就执行。
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    public abstract boolean leaseReturn(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
                                        HashMap<String, Double> toRightMap);

    /**
     * 租赁操作，判断各权利是否均操作阈值，符合条件就执行。
     *
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    public abstract boolean lease(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
                                  HashMap<String, Double> toRightMap);

    /**
     * 抵押操作，判断各权利是否均操作阈值，符合条件就执行。
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    public abstract boolean mortgage(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap);

    /**
     * 馈赠操作，判断各权利是否均操作阈值，符合条件就执行。
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param toRightMap
     *            此操作执行成功后，接收者的分配rightMap
     * @return true or false
     */
    public abstract boolean gift(HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        HashMap<String, Double> toRightMap);

    /**
     * 销毁操作，判断各权利是否均操作阈值，符合条件就执行。
     * 
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @return true or false
     */
    public abstract boolean destroy(HashMap<RightEnum, AbstractRight> moldMap, String[] froms);

    /**
     * 更新资产价值操作，判断各权利是否超过阈值超过就执行操作
     *
     * @param assetId
     *            资产id
     * @param froms
     *            调用此操作的同意者数组
     * @param asset
     *            资产对象
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @return true or false
     */
    public abstract boolean update(String assetId, String[] froms, Asset asset, HashMap<RightEnum, AbstractRight> moldMap);

    /**
     * 各操作规则需要的权利集合定义
     *
     * @param operateType
     *            资产的操作方法
     * @return 所需要的权利集合
     */
    public abstract List<RightEnum> operateTypeRightList(MoldEnum operateType);

    /**
     * 添加日志对象
     */
    private Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 判断是否有对资产的操作方法进行执行的权利(比如：售卖(sell)、租赁(lease)、抵押(mortgage)、馈赠(gift)、销毁(destroy)等)并判断是否超过设定的比例阈值
     *
     * @param operateType
     *            资产的操作方法
     * @param moldMap
     *            资产对象与权利对象的映射hashMap
     * @param froms
     *            调用此操作的同意者数组
     * @param threshold
     *            阈值
     * @return true or false
     */
    public boolean isHasImplementRight(MoldEnum operateType, HashMap<RightEnum, AbstractRight> moldMap, String[] froms,
        double threshold) {

        // 判断用户是否具有相关权利
        // 遍历操作规则集合
        // System.out.println(froms);
        for (RightEnum rightEnum : operateTypeRightList(operateType)) {
            // 同意者的某权利占比总和
            double total = 0.0;
            // 遍历froms得到username
            // 测试专用，对比forms与rightEnum中user_address的对比
            for (String from : froms) {
                // 判断权利对应的rightMap<username, percentage>中是否存在转移者username这个key
                if (moldMap.get(rightEnum).rightMap.containsKey(from)) {

                    //测试，控制台标准输出rightEnum与forms内容
                    log.info("mold中所规定的权属：" + JSONObject.toJSONString(moldMap.get(rightEnum).rightMap));
                    log.info("同意者组：" + JSONObject.toJSONString(froms));

                    // 存在，判断转移者的相关权利占有比例是否操作阈值
                    // 获取转移者权利占有比例
                    double userPercentage = moldMap.get(rightEnum).rightMap.get(from);
                    total = PercentageOperate.add(total, userPercentage);
                } else {
                    return false;
                }
            }
            // 与阈值相比较，调用工具类中double数据类型的比较方法
            if (!(PercentageOperate.compare(total, threshold) || PercentageOperate.equal(total, threshold))) {
                return false;
            }
        }
        return true;
    }

}
